#include "DXUT.h"
#include "DXUTDirect3DApplication.h"
#include "DXUTDirect3D9Support.h"
#include "DXUTDirect3D10Support.h"

DXUTDirect3DApplication *DXUTDirect3DApplication::s_app = 0;
IDirect3D9Support *DXUTDirect3DApplication::s_d3d9Support = 0;
IDirect3D10Support *DXUTDirect3DApplication::s_d3d10Support = 0;

DXUTDirect3DApplication *DXUTDirect3DApplication::GetInstance()
{
	return new DXUTDirect3DApplication();
}

DXUTDirect3DApplication::DXUTDirect3DApplication()
{
	s_app = this;
	DXUTSetCallbackFrameMove(FrameMoveCB);
	DXUTSetCallbackKeyboard(KeyboardCB);
	DXUTSetCallbackMouse(MouseCB);
	DXUTSetCallbackMsgProc(MsgProcCB);
	DXUTSetCallbackDeviceChanging(ModifyDeviceSettingsCB);
	DXUTSetCallbackDeviceRemoved(DeviceRemovedCB);

	if (IDirect3D9Support *support = GetDirect3D9Support())
	{
		s_d3d9Support = support;
		// Set the D3D9 DXUT callbacks. Remove these sets if the app doesn't need to support D3D9
		DXUTSetCallbackD3D9DeviceAcceptable(IsD3D9DeviceAcceptableCB);
		DXUTSetCallbackD3D9DeviceCreated(OnD3D9CreateDeviceCB);
		DXUTSetCallbackD3D9DeviceReset(OnD3D9ResetDeviceCB);
		DXUTSetCallbackD3D9FrameRender(OnD3D9FrameRenderCB);
		DXUTSetCallbackD3D9DeviceLost(OnD3D9LostDeviceCB);
		DXUTSetCallbackD3D9DeviceDestroyed(OnD3D9DestroyDeviceCB);
	}
	if (IDirect3D10Support *support = GetDirect3D10Support())
	{
		s_d3d10Support = support;
		// Set the D3D10 DXUT callbacks. Remove these sets if the app doesn't need to support D3D10
		DXUTSetCallbackD3D10DeviceAcceptable(IsD3D10DeviceAcceptableCB);
		DXUTSetCallbackD3D10DeviceCreated(OnD3D10CreateDeviceCB);
		DXUTSetCallbackD3D10SwapChainResized(OnD3D10ResizedSwapChainCB);
		DXUTSetCallbackD3D10FrameRender(OnD3D10FrameRenderCB);
		DXUTSetCallbackD3D10SwapChainReleasing(OnD3D10ReleasingSwapChainCB);
		DXUTSetCallbackD3D10DeviceDestroyed(OnD3D10DestroyDeviceCB);
	}
	if (!s_d3d9Support && !s_d3d10Support)
	{
		throw "No Direct3D9 or Direct3D10 support!";
	}
}

void DXUTDirect3DApplication::Initialize()
{
	DXUTInit( true, true, NULL ); // Parse the command line, show msgboxes on error, no extra command line params
	DXUTSetCursorSettings( true, true ); // Show the cursor and clip it when in full screen
	DXUTCreateWindow( L"EmptyProject10" );
	DXUTCreateDevice( true, 640, 480 );
}

int DXUTDirect3DApplication::Run()
{
	DXUTMainLoop(); // Enter into the DXUT render loop

	// Perform any application-level cleanup here

	return DXUTGetExitCode();
}

IDirect3D9Support *DXUTDirect3DApplication::GetDirect3D9Support() const
{
	return DXUTDirect3D9Support::GetInstance();
}

IDirect3D10Support *DXUTDirect3DApplication::GetDirect3D10Support() const
{
	return DXUTDirect3D10Support::GetInstance();
}

//--------------------------------------------------------------------------------------
// Called right before creating a D3D9 or D3D10 device, allowing the app to modify the device settings as needed
//--------------------------------------------------------------------------------------
bool DXUTDirect3DApplication::ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings )
{
	return true;
}

//--------------------------------------------------------------------------------------
// Handle updates to the scene.  This is called regardless of which D3D API is used
//--------------------------------------------------------------------------------------
void DXUTDirect3DApplication::OnFrameMove( double fTime, float fElapsedTime )
{

}

//--------------------------------------------------------------------------------------
// Handle messages to the application
//--------------------------------------------------------------------------------------
LRESULT DXUTDirect3DApplication::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing )
{
	return 0;
}

//--------------------------------------------------------------------------------------
// Handle key presses
//--------------------------------------------------------------------------------------
void DXUTDirect3DApplication::OnKeyboard( UINT nChar, bool bKeyDown, bool bAltDown )
{

}

//--------------------------------------------------------------------------------------
// Handle mouse button presses
//--------------------------------------------------------------------------------------
void DXUTDirect3DApplication::OnMouse( bool bLeftButtonDown, bool bRightButtonDown, bool bMiddleButtonDown, bool bSideButton1Down, bool bSideButton2Down, int nMouseWheelDelta, int xPos, int yPos )
{

}

//--------------------------------------------------------------------------------------
// Call if device was removed.  Return true to find a new device, false to quit
//--------------------------------------------------------------------------------------
bool DXUTDirect3DApplication::OnDeviceRemoved()
{
	return true;
}
